import { AimOutlined, MenuUnfoldOutlined, TagTwoTone } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { App, Button, Drawer, Flex, Image, Radio, Space, Spin, Tree } from 'antd';
import React, { useEffect, useRef, useState } from 'react';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import s from './index.less';
let scene: any;
let sceneView: any;
let pointCloudAche: any;
let sceneElements: any = [];
let allCubeLine: any = [];
let aspect = 0; // the canvas default
let allObjectAche: any = [];
let scene1: any;
let render1: any;
let camera1: any;
let camera: any, renderer: any;
const Mark: React.FC = () => {
  const fov = 59.7;
  const near = 0.1;
  const far = 100000;
  const [expandedKeys, setExpandedKeys] = useState<any>([]);
  const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
  const [autoExpandParent, setAutoExpandParent] = useState<boolean>(true);
  const [treeData, setTreeData] = useState([]);
  const [selecetedKeys, setSelecetedKeys] = useState<any>([]);
  const [visible, setVisible] = useState(false);
  const [isShowSign, setIsShowSign] = useState(false);
  const [src, setSrc] = useState(`${DOMAIN}/image.jpg`);
  const [imgLoading0, setImgLoading0] = useState(true);
  const [imgLoading1, setImgLoading1] = useState(true);
  const [imgLoading2, setImgLoading2] = useState(true);
  const [imgLoading3, setImgLoading3] = useState(true);
  const [imgLoading4, setImgLoading4] = useState(true);
  const [imgLoading5, setImgLoading5] = useState(true);
  const [loading3D, setLoading3D] = useState(true);
  const intl = useIntl();

  const imgLoadingMap: any = {
    0: setImgLoading0,
    1: setImgLoading1,
    2: setImgLoading2,
    3: setImgLoading3,
    4: setImgLoading4,
    5: setImgLoading5,
  };

  let mainViewRef = useRef<any>(null);
  let cvRef = useRef<any>(null);
  let antImgRef = useRef<any>(null);

  function changeLineSegmentsColor(ele: any, select = true) {
    let finalColor: any = [];
    const color = new THREE.Color(0x0000ff);
    let color2 = new THREE.Color(0xffffff);
    if (select) {
      color2 = new THREE.Color(0xff0000);
    }
    // 1 3 7 8
    for (let i = 0; i < 12; i++) {
      if (i === 1 || i === 3 || i === 7 || i === 8) {
        finalColor.push(color.r, color.g, color.b);
        finalColor.push(color.r, color.g, color.b);
      } else {
        finalColor.push(color2.r, color2.g, color2.b);
        finalColor.push(color2.r, color2.g, color2.b);
      }
    }
    ele.geometry.setAttribute('color', new THREE.Float32BufferAttribute(finalColor, 3));
  }

  function choose(select: any = null) {
    allCubeLine.forEach((item: any) => {
      changeLineSegmentsColor(item, false);
    });
    for (let i = 0; i < allCubeLine.length; i++) {
      const element = allCubeLine[i];
      if (select === element.name) {
        setSelecetedKeys([element.name]);
        changeLineSegmentsColor(element, true);
        return;
      }
    }
    setSelecetedKeys([]);
  }

  class PickHelper {
    raycaster: any;
    pickedObject: any;
    pickedObjectSavedColor: number;
    constructor() {
      this.raycaster = new THREE.Raycaster();
      this.pickedObject = null;
      this.pickedObjectSavedColor = 0;
    }
    pick(normalizedPosition: any, scene: any, camera: any) {
      // 恢复上一个被拾取对象的颜色
      // 发出射线
      this.raycaster.setFromCamera(normalizedPosition, camera);
      // 获取与射线相交的对象
      const arr: any = scene.children.filter((item: any) => {
        return item.type === 'Mesh';
      });
      const intersectedObjects = this.raycaster.intersectObjects(arr);
      if (intersectedObjects.length === 0) {
        choose();
      }
      if (intersectedObjects.length) {
        // 找到第一个对象，它是离鼠标最近的对象
        const first: any = intersectedObjects[0];
        choose(first.object.name);
      }
    }
  }
  const pickHelper = new PickHelper();

  function clearObject() {
    allObjectAche.forEach((val: any) => {
      scene.remove(val);
      sceneView.remove(val);
      if (val.geometry) {
        val.geometry.dispose();
      }
      if (val.material) {
        val.material.dispose();
      }
      if (typeof val.dispose === 'function') {
        val.dispose();
      }
    });
    allObjectAche = [];
    allCubeLine = [];
  }

  function clearPointCloud() {
    if (pointCloudAche) {
      scene.remove(pointCloudAche);
      pointCloudAche.geometry.dispose();
      pointCloudAche.material.dispose();
    }
  }

  function createMatrixFromCameraInternal(option: any, w: any, h: any, near: any, far: any) {
    let { fx, fy, cy, cx } = option;
    // return new THREE.Matrix4().set(
    //     2*fx / w,       0,                   1 - 2*cx / w,                 0,
    //     0,           2*fy / h,          2*cy / h - 1,                      0,
    //     0,             0,            (near + far) / (near - far),   2*far*near / (near - far),
    //     0,             0,                      -1.0,                       0);

    return new THREE.Matrix4().set(
      (2 * fx) / w,
      0,
      1 - (2 * cx) / w,
      0,
      0,
      (2 * fy) / h,
      (2 * cy) / h - 1,
      0,
      0,
      0,
      (near + far) / (near - far),
      (2 * far * near) / (near - far),
      0,
      0,
      -1,
      0,
    );
  }
  function getI(k: any) {
    const obj = {
      cx: k[0][2],
      cy: k[1][2],
      fx: k[0][0],
      fy: k[1][1],
    };
    return obj;
  }
  function getRT(rt: any) {
    const res = new THREE.Matrix4();
    res.set(
      rt[0][0],
      rt[0][1],
      rt[0][2],
      rt[0][3],
      rt[1][0],
      rt[1][1],
      rt[1][2],
      rt[1][3],
      rt[2][0],
      rt[2][1],
      rt[2][2],
      rt[2][3],
      rt[3][0],
      rt[3][1],
      rt[3][2],
      rt[3][3],
    );
    res.transpose().invert();
    return res;
  }
  function transI(str: any) {
    // 将字符串按逗号分割成数组
    let strArr = str.split(',');
    // 定义二维数组
    let result = [];
    // 循环遍历原始数组，每三个元素为一组添加到二维数组中
    for (let i = 0; i < strArr.length; i += 3) {
      result.push([parseFloat(strArr[i]), parseFloat(strArr[i + 1]), parseFloat(strArr[i + 2])]);
    }
    return result;
  }
  function transK(rotation: any, translation: any) {
    const r = rotation.split(',').map((n: any) => parseFloat(n));
    const t = translation.split(',').map((n: any) => parseFloat(n));
    const res = new THREE.Matrix4();
    res.set(r[0], r[1], r[2], t[0], r[3], r[4], r[5], t[1], r[6], r[7], r[8], t[2], 0, 0, 0, 1);
    res.transpose();
    let result = [];
    const k = res.elements;
    for (let i = 0; i < k.length; i += 4) {
      result.push([k[i], k[i + 1], k[i + 2], k[i + 3]]);
    }
    return result;
  }

  // 六个视图设置（看作cv）与图片大小一致(参数是cv)
  function resizeView(ele: any) {
    // 获取容器的宽度和高度
    const containerWidth = ele.parentNode.clientWidth;
    const containerHeight = ele.parentNode.clientHeight;
    // 获取图片的原始宽度和高度
    const originalWidth = ele.previousElementSibling.naturalWidth;
    const originalHeight = ele.previousElementSibling.naturalHeight;
    // 获取图片经过 object-fit 处理后的显示宽度和高度
    let displayWidth, displayHeight;
    const containerRatio = containerWidth / containerHeight;
    const imageRatio = originalWidth / originalHeight;
    if (imageRatio > containerRatio) {
      displayWidth = containerWidth;
      displayHeight = containerWidth / imageRatio;
    } else {
      displayHeight = containerHeight;
      displayWidth = containerHeight * imageRatio;
    }
    ele.style.width = displayWidth + 'px';
    ele.style.height = displayHeight + 'px';
  }

  function main(obj: any, sceneElements: any, scene: any, renderer: any, sceneView: any) {
    function resetCameraParams(camera: any, obj: any, near: any, far: any, ind: any, ele: any) {
      const imgPath = obj.images[ind];
      const loading = new THREE.LoadingManager(() => {
        imgLoadingMap[ind](false);
      });
      const textureLoader = new THREE.TextureLoader(loading);
      textureLoader.load(imgPath, (texture: any) => {
        const imgW = texture.image.naturalWidth;
        const imgH = texture.image.naturalHeight;
        const oldNode = ele.previousElementSibling;
        ele.parentNode.replaceChild(texture.image, oldNode);
        resizeView(ele);
        const camera_internal = getI(obj.camera[ind].cam_K);
        const camera_external = getRT(obj.camera[ind].extrinsic);
        let matrix = new THREE.Matrix4().copy(camera_external);
        matrix.transpose().premultiply(new THREE.Matrix4().makeScale(1, -1, -1));
        matrix.invert();
        matrix.decompose(camera.position, camera.quaternion, camera.scale);
        const I = createMatrixFromCameraInternal(camera_internal, imgW, imgH, near, far);
        camera.aspect = imgW / imgH;
        camera.updateMatrixWorld();
        camera.projectionMatrix.copy(I);
      });
    }

    function drawTarget(ar: any) {
      let obj: any = {
        title: '目标检测',
        key: '目标检测',
        children: [],
        Sign: [],
      };
      let uuid: any = [];
      if (ar.length <= 0) {
        return [[], uuid];
      }
      ar.forEach((item: any, ind: any) => {
        let o: any = {};
        const x = item.meta.geometry.positionX;
        const y = item.meta.geometry.positionY;
        const z = item.meta.geometry.positionZ;
        const l = item.meta.geometry.length;
        const w = item.meta.geometry.width;
        const h = item.meta.geometry.height;
        const yaw = item.meta.geometry.yaw;
        // const dir = new THREE.Vector3(1, 0, 0);
        // const origin = new THREE.Vector3(x, y, z);
        // const length = l;
        // const hex = 0x00ff00;
        // const width = length * 0.1; // 箭头宽度，可以根据需要调整比例

        // const arrowHelper = new THREE.ArrowHelper(dir, origin, length, hex, width);
        // arrowHelper.setLength(l / 2, 1, 0.5);

        const geometry = new THREE.BoxGeometry(l, w, h);
        const edges = new THREE.EdgesGeometry(geometry);

        const mygeometry = new THREE.BufferGeometry();
        mygeometry.setAttribute(
          'position',
          new THREE.Float32BufferAttribute(edges.attributes.position.array, 3),
        );
        const line = new THREE.LineSegments(
          // edges,
          // new THREE.LineBasicMaterial({ color: 0xffffff }),
          mygeometry,
          new THREE.LineBasicMaterial({ vertexColors: true }),
        );
        changeLineSegmentsColor(line, false);

        const myBox = new THREE.Mesh(
          geometry,
          new THREE.MeshBasicMaterial({
            color: 0xffffff,
            transparent: true,
            opacity: 0,
            depthTest: false,
          }),
        );
        // myBox.renderOrder = 0;
        line.name = item.id;
        myBox.name = item.id;
        line.position.set(x, y, z);
        myBox.position.set(x, y, z);
        line.rotateZ(yaw);
        myBox.rotateZ(yaw);
        // arrowHelper.rotateZ(yaw);
        // line.rotateZ((Math.PI * yaw) / 180);
        // myBox.rotateZ((Math.PI * yaw) / 180);
        // arrowHelper.rotateZ((Math.PI * yaw) / 180);
        scene.add(myBox);
        scene.add(line);
        // scene.add(arrowHelper);
        allCubeLine.push(line);
        const myBoxClone = myBox.clone();
        const lineClone = line.clone();
        // const arrowHelperClone = arrowHelper.clone();
        sceneView.add(myBoxClone);
        sceneView.add(lineClone);
        // sceneView.add(arrowHelperClone);
        o.title = ind;
        // o.key = myBox.uuid;
        o.key = item.id;
        o.Sign = [];
        // o.Sign.push(myBox, line, arrowHelper, lineClone, myBoxClone, arrowHelperClone);
        o.Sign.push(myBox, line, lineClone, myBoxClone);
        o.children = [];
        obj.children.push(o);
        // uuid.push(myBox.uuid);
        uuid.push(item.id);
        // allObjectAche.push(myBox, line, arrowHelper, lineClone, myBoxClone, arrowHelperClone);
        allObjectAche.push(myBox, line, lineClone, myBoxClone);
      });
      return [[obj], uuid];
    }

    // -------------------------画目标检测物-------------------------

    // -------------------------画目标车道线,路缘石,停车线,斑马线-------------------------
    function createLines(l: any, name?: any, color = 'white') {
      let obj: any = {
        title: name,
        key: name,
        children: [],
        Sign: [],
        color,
      };
      let uuid: any = [];
      if (l.length <= 0) {
        return [[], uuid];
      }
      l.forEach((one: any, ind: any) => {
        let o: any = {};
        const points: any = [];
        const material = new THREE.LineBasicMaterial({ color });
        one.points_xyz.forEach((item: any) => {
          points.push(new THREE.Vector3(item.x, item.y, item.z));
        });
        const geometry = new THREE.BufferGeometry().setFromPoints(points);
        const line = new THREE.Line(geometry, material);
        o.color = color;
        o.title = ind;
        o.key = line.uuid;
        o.Sign = [];
        o.children = [];
        obj.children.push(o);
        const lineView = line.clone();
        o.Sign.push(line, lineView);
        allObjectAche.push(line, lineView);
        uuid.push(line.uuid);
        scene.add(line);
        sceneView.add(lineView);
      });

      return [[obj], uuid];
    }
    // -------------------------画目标车道线,路缘石,停车线,斑马线-------------------------

    // -------------------------画断点,交叉点，dash， start-------------------------
    function createP(l: any, name?: any) {
      // var res: any = [];
      let obj: any = {
        title: name,
        key: name,
        children: [],
        Sign: [],
        color: '#00ff00',
      };
      let uuid: any = [];
      if (l.length <= 0) {
        return [[], uuid];
      }
      l.forEach((one: any, ind: any) => {
        let o: any = {};
        const geometry = new THREE.SphereGeometry(0.2, 32, 32); // 参数分别为半径、水平和垂直方向的分段数
        const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 }); // 使用基础材质，设置颜色为红色
        const points = new THREE.Mesh(geometry, material);
        points.position.set(one.points_xyz.x, one.points_xyz.y, one.points_xyz.z);

        // 将点添加到场景中
        o.color = '#00ff00';
        o.title = ind;
        o.key = points.uuid;
        o.Sign = [];
        o.children = [];
        obj.children.push(o);
        const pointClone = points.clone();
        o.Sign.push(points, pointClone);
        allObjectAche.push(points, pointClone);
        uuid.push(points.uuid);
        scene.add(points);
        sceneView.add(pointClone);
      });
      return [[obj], uuid];
    }
    // -------------------------画断点,交叉点，dash， end-------------------------

    // 画点云 ---------------------------------start---------------------------------
    function parsePointCloud(data: any) {
      const dataView = new DataView(data);
      // 假设每个点的数据是三个浮点数（X、Y、Z），你需要根据实际格式进行解析
      const numPoints = dataView.byteLength / 16; // 12 字节 = 3 个浮点数 * 4 字节/浮点数
      // const numPoints = 31; // 12 字节 = 3 个浮点数 * 4 字节/浮点数
      const points = new Float32Array(numPoints * 3);
      for (let i = 0; i < numPoints; i++) {
        const offset = i * 16;
        let x = dataView.getFloat32(offset, true);
        let y = dataView.getFloat32(offset + 4, true);
        let z = dataView.getFloat32(offset + 8, true);
        points[i * 3] = x;
        points[i * 3 + 1] = y;
        points[i * 3 + 2] = z;
      }
      return points;
    }
    function createPoints(path: any) {
      const loading = new THREE.LoadingManager(() => {
        setLoading3D(false);
      });
      const loader = new THREE.FileLoader(loading);
      // 设置加载器的 responseType 为 'arraybuffer'
      loader.setResponseType('arraybuffer');
      loader.load(path, function (data: any) {
        const points = parsePointCloud(data);
        // 创建点云对象
        const geometry = new THREE.BufferGeometry();
        geometry.setAttribute('position', new THREE.Float32BufferAttribute(points, 3));
        const material = new THREE.PointsMaterial({
          color: 0xff55ff,
          size: 0.1,
          opacity: 1,
          // transparent: true,
        });
        clearPointCloud();
        const pointCloud = new THREE.Points(geometry, material);
        pointCloudAche = pointCloud;
        // 将点云对象添加到场景
        scene.add(pointCloud);
      });
    }
    // 画点云 ---------------------------------end---------------------------------
    function mainUpdate(obj: any) {
      clearObject();
      let [leaf1, uuid1] = createLines(obj.laneLines, 'laneLines', 'red');
      let [leaf2, uuid2] = createLines(obj.curb, 'curb', 'blue');
      let [leaf3, uuid3] = createLines(obj.stopline, 'stopline', 'green');
      let [leaf4, uuid4] = createLines(obj.zebracrossing, 'zebracrossing', '#48d1cc');
      let [leafP1, uuidP1] = createP(obj.breakpoint, 'breakpoint');
      let [leafP2, uuidP2] = createP(obj.crosspoints, 'crosspoints');
      let [leafP3, uuidP3] = createP(obj.dashed_solid, 'dashed_solid');
      let [leafTar1, uuidTar1] = drawTarget(obj.targetData);
      let tree: any = [
        ...leaf1,
        ...leaf2,
        ...leaf3,
        ...leaf4,
        ...leafP1,
        ...leafP2,
        ...leafP3,
        ...leafTar1,
      ];
      let allCheckedKeys: any = [
        ...uuid1,
        ...uuid2,
        ...uuid3,
        ...uuid4,
        ...uuidP1,
        ...uuidP2,
        ...uuidP3,
        ...uuidTar1,
      ];
      createPoints(obj.path);
      setTreeData(tree);
      setCheckedKeys(allCheckedKeys);
    }

    sceneElements.forEach((item: any, ind: any) => {
      if (ind <= 5) {
        const { camera, elem } = item;
        resetCameraParams(camera, obj, near, far, ind, elem);
      }
    });
    mainUpdate(obj);
  }

  async function chooseItem(val: any) {
    const { typeCode, sceneElements, scene, renderer } = val;
    let obj: any = {
      laneLines: [],
      curb: [],
      stopline: [],
      zebracrossing: [],
      crosspoints: [],
      dashed_solid: [],
      breakpoint: [],
      path: '',
      targetData: [], //目标检测的数据
      camera: [],
      images: [],
    };
    let data0: any;
    let data1: any;
    let data2: any;
    let data3: any;
    let data4: any;
    let data5: any;

    // 同步初使化到此结束
    if (typeCode === 'bev') {
      // 目标检测
      let marks: any = await fetch('3d/params2.json');
      marks = await marks.json();
      obj.path = `${DOMAIN}/point2.bin`;
      obj.images[0] = `${DOMAIN}/front2.jpg`;
      obj.images[1] = `${DOMAIN}/left_front2.jpg`;
      obj.images[2] = `${DOMAIN}/right_front2.jpg`;
      obj.images[3] = `${DOMAIN}/left_back2.jpg`;
      obj.images[4] = `${DOMAIN}/right_back2.jpg`;
      obj.images[5] = `${DOMAIN}/back2.jpg`;
      obj.targetData = marks.sd_result.items;
      data0 = marks.params.CAM_FRONT;
      data1 = marks.params.CAM_FRONT_LEFT;
      data2 = marks.params.CAM_FRONT_RIGHT;
      data3 = marks.params.CAM_BACK_LEFT;
      data4 = marks.params.CAM_BACK_RIGHT;
      data5 = marks.params.CAM_BACK;
      data0.cam_K = transI(data0.intrinsic.k);
      data1.cam_K = transI(data1.intrinsic.k);
      data2.cam_K = transI(data2.intrinsic.k);
      data3.cam_K = transI(data3.intrinsic.k);
      data4.cam_K = transI(data4.intrinsic.k);
      data5.cam_K = transI(data5.intrinsic.k);
      data0.extrinsic = transK(data0.extrinsic.r, data0.extrinsic.t);
      data1.extrinsic = transK(data1.extrinsic.r, data1.extrinsic.t);
      data2.extrinsic = transK(data2.extrinsic.r, data2.extrinsic.t);
      data3.extrinsic = transK(data3.extrinsic.r, data3.extrinsic.t);
      data4.extrinsic = transK(data4.extrinsic.r, data4.extrinsic.t);
      data5.extrinsic = transK(data5.extrinsic.r, data5.extrinsic.t);
      obj.camera = [data0, data1, data2, data3, data4, data5];
      main(obj, sceneElements, scene, renderer, sceneView);
    } else {
      // 车道线
      let marks: any = await fetch('3d/params1.json');
      marks = await marks.json();
      obj.path = `${DOMAIN}/point1.bin`;
      obj.images[0] = `${DOMAIN}/front1.jpg`;
      obj.images[1] = `${DOMAIN}/left_front1.jpg`;
      obj.images[2] = `${DOMAIN}/right_front1.jpg`;
      obj.images[3] = `${DOMAIN}/left_back1.jpg`;
      obj.images[4] = `${DOMAIN}/right_back1.jpg`;
      obj.images[5] = `${DOMAIN}/back1.jpg`;
      marks.instance_labels.forEach((item: any) => {
        if (item.name === 'lane_lines') {
          obj.laneLines = item.values;
        }
        if (item.name === 'curb') {
          obj.curb = item.values;
        }
        if (item.name === 'stopline') {
          obj.stopline = item.values;
        }
        if (item.name === 'zebracrossing') {
          obj.zebracrossing = item.values;
        }
        if (item.name === 'breakpoint') {
          obj.breakpoint = item.values;
        }
        if (item.name === 'crosspoints') {
          obj.crosspoints = item.values;
        }
        if (item.name === 'dashed_solid') {
          obj.dashed_solid = item.values;
        }
      });
      data0 = marks.camera_parameters.CAM_FRONT;
      data1 = marks.camera_parameters.CAM_FRONT_LEFT;
      data2 = marks.camera_parameters.CAM_FRONT_RIGHT;
      data3 = marks.camera_parameters.CAM_BACK_LEFT;
      data4 = marks.camera_parameters.CAM_BACK_RIGHT;
      data5 = marks.camera_parameters.CAM_BACK;
      obj.camera = [data0, data1, data2, data3, data4, data5];
      main(obj, sceneElements, scene, renderer, sceneView);
    }
  }

  async function updateList() {
    chooseItem({ sceneElements, scene, renderer, typeCode: '' });
  }

  function updateCvRef(val?: any) {
    cvRef.current.style.width = antImgRef.current.offsetWidth + 'px';
    cvRef.current.style.height = antImgRef.current.offsetHeight + 'px';
    if (val) {
      const { x, y, rotate, scale, flipX, flipY } = val.transform;
      cvRef.current.style.transform = `translate3d(${x}px, ${y}px, 0px) scale3d(${
        flipX ? -scale : scale
      }, ${flipY ? -scale : scale}, 1) rotate(${rotate}deg)`;
    }
    render1.setSize(antImgRef.current.offsetWidth, antImgRef.current.offsetHeight);
    render1.render(scene1, camera1);
  }

  const onExpand = (expandedKeysValue: React.Key[]) => {
    setExpandedKeys(expandedKeysValue);
    setAutoExpandParent(false);
  };

  const onCheck = (checkedKeysValue: any, v: any) => {
    function loop(node: any, b: any) {
      // node传进来是一个对象
      node.Sign.forEach((val: any) => {
        val.visible = b;
      });
      if (node.children.length > 0) {
        node.children.forEach((item: any) => {
          loop(item, b);
        });
      }
    }
    loop(v.node, v.checked);
    setCheckedKeys(checkedKeysValue);
  };
  function getCanvasRelativePosition(event: any) {
    const canvas = event.target;
    const rect = canvas.getBoundingClientRect();
    return {
      x: ((event.clientX - rect.left) * canvas.offsetWidth) / rect.width,
      y: ((event.clientY - rect.top) * canvas.offsetHeight) / rect.height,
    };
  }
  const pickPosition = { x: 0, y: 0 };
  function setPickPosition(event: any) {
    const canvas = event.target;
    const pos = getCanvasRelativePosition(event);
    pickPosition.x = (pos.x / canvas.offsetWidth) * 2 - 1;
    pickPosition.y = (pos.y / canvas.offsetHeight) * -2 + 1; // note we flip Y
    pickHelper.pick(pickPosition, scene, camera);
  }
  function clearPickPosition() {
    // 对于触屏，不像鼠标总是能有一个位置坐标，
    // 如果用户不在触摸屏幕，我们希望停止拾取操作。
    // 因此，我们选取一个特别的值，表明什么都没选中
    pickPosition.x = -100000;
    pickPosition.y = -100000;
  }

  const handlePre = (e: any) => {
    const src = e.target && e.target.src;
    if (!src) {
      return;
    }
    while (scene1.children.length > 0) {
      scene1.remove(scene1.children[0]);
    }
    const index = e.target.nextElementSibling.getAttribute('data-diagram').slice(3) - 1;
    setVisible(true);
    setSrc(src);
    scene1.copy(sceneView);
    camera1.copy(sceneElements[index].camera);
  };

  const [valueRadio, setValueRadio] = useState(1);

  const setAllImgLoading = () => {
    setImgLoading0(true);
    setImgLoading1(true);
    setImgLoading2(true);
    setImgLoading3(true);
    setImgLoading4(true);
    setImgLoading5(true);
    setLoading3D(true);
  };

  const onChange = (e: any) => {
    setAllImgLoading();
    setValueRadio(e.target.value);
    if (e.target.value === 1) {
      chooseItem({
        typeCode: '',
        sceneElements,
        scene,
        renderer,
      });
    } else {
      chooseItem({
        typeCode: 'bev',
        sceneElements,
        scene,
        renderer,
      });
    }
  };

  useEffect(() => {
    let isChange = false;
    const canvas: any = document.querySelector('#c');
    renderer = new THREE.WebGLRenderer({ antialias: true, canvas, alpha: true });
    renderer.outputColorSpace = 'display-p3-linear';
    scene = new THREE.Scene();
    sceneView = new THREE.Scene();

    clearPickPosition();
    function addScene(elem: any, fn: any, camera: any) {
      sceneElements.push({ elem, fn, camera });
    }
    document.querySelectorAll('[data-diagram]').forEach((elem: any) => {
      const sceneName = elem.dataset.diagram;
      if (sceneName === 'box') {
        aspect = elem.offsetWidth / elem.offsetHeight;
        const cameraItem = new THREE.PerspectiveCamera(fov, aspect, near, far);
        camera = cameraItem;
        cameraItem.position.set(-50, 50, 50);
        cameraItem.up = new THREE.Vector3(0, 0, 1);
        cameraItem.lookAt(0, 0, 0);
        const controls: any = new OrbitControls(cameraItem, elem);
        controls.enableDamping = true;
        controls.dampingFactor = 0.2;
        controls.noZoom = true;
        controls.noPan = true;
        scene.add(cameraItem);
        const axesHelper = new THREE.AxesHelper(10);
        scene.add(axesHelper);
        controls.addEventListener('change', () => {
          isChange = true;
        });
        controls.addEventListener('start', function () {
          isChange = false;
        });
        addScene(
          elem,
          () => {
            cameraItem.aspect = aspect;
            cameraItem.updateProjectionMatrix();
            renderer.render(scene, cameraItem);
          },
          cameraItem,
        );
      }
      if (sceneName.indexOf('cam') !== -1) {
        const cameraItem = new THREE.PerspectiveCamera();
        addScene(
          elem,
          () => {
            renderer.render(sceneView, cameraItem);
          },
          cameraItem,
        );
      }
    });
    mainViewRef.current.addEventListener(
      'click',
      (e: any) => {
        if (isChange) {
          return;
        }
        setPickPosition(e);
      },
      false,
    );

    function resizeRendererToDisplaySize(renderer: any) {
      const canvas = renderer.domElement;
      const width = canvas.clientWidth;
      const height = canvas.clientHeight;
      const needResize = canvas.width !== width || canvas.height !== height;
      if (needResize) {
        renderer.setSize(width, height, false);
      }
      return needResize;
    }

    function render(time: any) {
      resizeRendererToDisplaySize(renderer);

      renderer.setScissorTest(false);
      // renderer.setClearColor(clearColor, 0);
      renderer.clear(true, true);
      renderer.setScissorTest(true);

      // const transform = `translateY(-${window.scrollY}px)`;
      // renderer.domElement.style.transform = transform;
      for (const { elem, fn } of sceneElements) {
        // get the viewport relative position of this element
        const rect = elem.getBoundingClientRect();
        const { left, right, top, bottom, width, height } = rect;
        const isOffscreen =
          bottom < 0 ||
          top > renderer.domElement.clientHeight ||
          right < 0 ||
          left > renderer.domElement.clientWidth;

        if (!isOffscreen) {
          const positiveYUpBottom = renderer.domElement.clientHeight - bottom;
          renderer.setScissor(left, positiveYUpBottom, width, height);
          renderer.setViewport(left, positiveYUpBottom, width, height);
          fn(time, rect);
        }
      }

      requestAnimationFrame(render);
    }
    requestAnimationFrame(render);
    updateList();
    function onreset() {
      aspect = mainViewRef.current.offsetWidth / mainViewRef.current.offsetHeight;
      cvRef.current.style.width = antImgRef.current.offsetWidth + 'px';
      cvRef.current.style.height = antImgRef.current.offsetHeight + 'px';
      // 六个视图大小自适应变换
      sceneElements.forEach((item: any) => {
        resizeView(item.elem);
      });
    }
    window.addEventListener('resize', onreset);

    scene1 = new THREE.Scene();
    camera1 = new THREE.PerspectiveCamera();
    render1 = new THREE.WebGLRenderer({ antialias: true, canvas: cvRef.current, alpha: true });
    render1.outputColorSpace = 'display-p3-linear';
    scene1.add(camera1);
    return () => {
      sceneElements = [];
      window.removeEventListener('resize', onreset);
    };
  }, []);

  return (
    <App style={{ height: '100%', display: 'flex', flexDirection: 'column' }}>
      <Image
        width={200}
        style={{ display: 'none' }}
        preview={{
          visible,
          src,
          afterOpenChange() {
            updateCvRef();
          },
          onVisibleChange: (value) => {
            setVisible(value);
          },
          forceRender: true,
          onTransform: (val) => {
            updateCvRef(val);
          },
          imageRender: (val) => {
            if (val.props.imgRef.current) {
              antImgRef.current = val.props.imgRef.current;
            }
            return (
              <>
                {val}
                <canvas className={s.preCv} ref={cvRef}></canvas>
              </>
            );
          },
        }}
      />
      <canvas id="c" className={s.c}></canvas>
      <div className={s.showPic}>
        <section style={{ flex: 1, position: 'relative' }}>
          <div className={s.point}>
            <div className={s.pointLeft}>
              <div className={s.row1}>
                <div className={s.front} onClick={handlePre}>
                  <img />
                  <div data-diagram="cam1">{<Spin spinning={imgLoading0} />}</div>
                </div>
              </div>
              <div className={s.row2}>
                <div className={s.row21}>
                  <div className={s.frontLeft} onClick={handlePre}>
                    <img />
                    <div data-diagram="cam2">{<Spin spinning={imgLoading1} />}</div>
                  </div>
                </div>
                <div className={s.row22}>
                  <div className={s.frontRight} onClick={handlePre}>
                    <img />
                    <div data-diagram="cam3">{<Spin spinning={imgLoading2} />}</div>
                  </div>
                </div>
              </div>
              <div className={s.row3}>
                <div className={s.row31}>
                  <div className={s.backLeft} onClick={handlePre}>
                    <img />
                    <div data-diagram="cam4">{<Spin spinning={imgLoading3} />}</div>
                  </div>
                </div>
                <div className={s.row32}>
                  <div className={s.backRight} onClick={handlePre}>
                    <img />
                    <div data-diagram="cam5">{<Spin spinning={imgLoading4} />}</div>
                  </div>
                </div>
              </div>
              <div className={s.row4}>
                <div className={s.back} onClick={handlePre}>
                  <img />
                  <div data-diagram="cam6">{<Spin spinning={imgLoading5} />}</div>
                </div>
              </div>
            </div>
            <div className={s.pointRight}>
              <div
                style={{
                  position: 'absolute',
                  left: '0',
                  top: '0',
                  display: 'flex',
                  justifyContent: 'center',
                  alignItems: 'center',
                  width: '100%',
                }}
              >
                <Spin size="large" spinning={loading3D}></Spin>
              </div>
              <div ref={mainViewRef} data-diagram="box"></div>
            </div>
            <Drawer
              title={intl.formatMessage({
                id: 'component.label',
                defaultMessage: '标签',
              })}
              onClose={() => setIsShowSign(false)}
              open={isShowSign}
            >
              <Tree
                checkable
                titleRender={(val: any) => {
                  let color = val.color ? val.color : '#11ffff';
                  return (
                    <>
                      <TagTwoTone twoToneColor={color} /> {val.title}
                    </>
                  );
                }}
                onExpand={onExpand}
                expandedKeys={expandedKeys}
                autoExpandParent={autoExpandParent}
                onCheck={onCheck}
                checkedKeys={checkedKeys}
                selectedKeys={selecetedKeys}
                onSelect={(val: any) => {
                  if (val[0].length === 36) {
                    setSelecetedKeys(val);
                    choose(val[0]);
                  } else {
                    setSelecetedKeys([]);
                    choose();
                  }
                }}
                treeData={treeData}
              />
            </Drawer>
          </div>
        </section>
      </div>
      <div className={s.imgBottom}>
        <Space>
          <Button
            size="small"
            onClick={() => {
              setIsShowSign(true);
            }}
          >
            {intl.formatMessage({
              id: 'component.label',
              defaultMessage: '标签',
            })}
          </Button>
          <Radio.Group
            onChange={onChange}
            value={valueRadio}
            options={[
              {
                value: 1,
                label: (
                  <Flex gap="small" justify="center" align="center" vertical>
                    <MenuUnfoldOutlined style={{ fontSize: 18 }} />
                    {intl.formatMessage({
                      id: 'component.laneLine',
                      defaultMessage: '车道线',
                    })}
                  </Flex>
                ),
              },
              {
                value: 2,
                label: (
                  <Flex gap="small" justify="center" align="center" vertical>
                    <AimOutlined style={{ fontSize: 18 }} />
                    {intl.formatMessage({
                      id: 'component.targetDetection',
                      defaultMessage: '目标检测',
                    })}
                  </Flex>
                ),
              },
            ]}
          />
        </Space>
      </div>
    </App>
  );
};

export default Mark;
